package 双指针或滑动窗口.可获得的最大点数1423;

public class Solution {
    /**
     * 计算从卡牌数组中抽取k张卡牌能获得的最大点数
     * 该方法通过滑动窗口算法来找出不需要抽取的卡牌子数组，以最大化抽取卡牌的总点数
     *
     * @param cardPoints 表示每张卡牌的点数的整数数组
     * @param k          表示可以抽取的卡牌数量
     * @return 返回从卡牌数组中抽取k张卡牌能获得的最大点数
     */
    public int maxScore(int[] cardPoints, int k) {
        // 计算所有卡牌点数的总和
        int sum = 0;
        int n = cardPoints.length;
        for (int num : cardPoints) {
            sum += num;
        }

        // 计算不需要抽取的卡牌数量
        int m = n - k;
        // 特殊情况处理：如果k等于n，即所有卡牌都要抽取，则直接返回总和
        if (m == 0) return sum;

        // 初始化窗口内卡牌点数的和
        int windowSum = 0;
        for (int i = 0; i < m; i++) {
            windowSum += cardPoints[i]; // 先填满窗口
        }

        // 初始化最小窗口和为当前窗口的和
        int minMs = windowSum;

        // 使用滑动窗口找出最小的m张卡牌点数和
        for (int i = m; i < n; i++) {
            // 滑动窗口：从窗口中移除最左边的卡牌，添加当前卡牌
            windowSum += cardPoints[i] - cardPoints[i - m];
            // 更新最小窗口和
            minMs = Math.min(minMs, windowSum);
        }

        // 返回最大点数，即总和减去不需要抽取的卡牌点数和
        return sum - minMs;
    }

}
